#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_wifi_api.h"
#include "lwip/ip_addr.h"
#include "lwip/netifapi.h"
#include "lwip/sockets.h"
#include "MQTTClient.h"
#include "hi_gpio.h"
#include "hi_io.h"
#include "hi_time.h"
#include <MQTTConnect.h>

#define DHT11_GPIO 7 // DHT11数据引脚
#define u8 unsigned char
#define DHT11_DQ_OUT_HIGH hi_gpio_set_ouput_val(DHT11_GPIO, HI_GPIO_VALUE1)
#define DHT11_DQ_OUT_LOW hi_gpio_set_ouput_val(DHT11_GPIO, HI_GPIO_VALUE0)

// MQTT全局变量
static MQTTClient mq_client;
unsigned char *onenet_mqtt_buf;
unsigned char *onenet_mqtt_readbuf;
int buf_size;
Network n;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
static u8 temperature = 0;
static u8 humidity = 0;
static hi_gpio_value DHT11_DQ_IN;

// DHT11底层驱动函数（复用原逻辑）
static u8 GPIOGETINPUT(hi_io_name id, hi_gpio_value *val)
{
    hi_gpio_get_input_val(id, val);
    return *val;
}

static void DHT11_IO_OUT(void) { hi_gpio_set_dir(DHT11_GPIO, HI_GPIO_DIR_OUT); }
static void DHT11_IO_IN(void)
{
    hi_gpio_set_dir(DHT11_GPIO, HI_GPIO_DIR_IN);
    hi_io_set_pull(DHT11_GPIO, HI_IO_PULL_NONE);
}

static void DHT11_Rst(void)
{
    DHT11_IO_OUT();
    DHT11_DQ_OUT_LOW;
    hi_udelay(20000);
    DHT11_DQ_OUT_HIGH;
    hi_udelay(35);
}

static u8 DHT11_Check(void)
{
    u8 retry = 0;
    DHT11_IO_IN();
    while (GPIOGETINPUT(DHT11_GPIO, &DHT11_DQ_IN) && retry < 100)
    {
        retry++;
        hi_udelay(1);
    }
    if (retry >= 100)
        return 1;
    retry = 0;
    while ((!GPIOGETINPUT(DHT11_GPIO, &DHT11_DQ_IN)) && retry < 100)
    {
        retry++;
        hi_udelay(1);
    }
    if (retry >= 100)
        return 1;
    return 0;
}

static u8 DHT11_Init(void)
{
    hi_io_set_func(DHT11_GPIO, HI_IO_FUNC_GPIO_7_GPIO);
    hi_gpio_set_dir(DHT11_GPIO, HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(DHT11_GPIO, HI_GPIO_VALUE1);
    DHT11_Rst();
    return DHT11_Check();
}

static u8 DHT11_Read_Bit(void)
{
    u8 retry = 0;
    while (GPIOGETINPUT(DHT11_GPIO, &DHT11_DQ_IN) && retry < 100)
    {
        retry++;
        hi_udelay(1);
    }
    retry = 0;
    while ((!GPIOGETINPUT(DHT11_GPIO, &DHT11_DQ_IN)) && retry < 100)
    {
        retry++;
        hi_udelay(1);
    }
    hi_udelay(40);
    return GPIOGETINPUT(DHT11_GPIO, &DHT11_DQ_IN) ? 1 : 0;
}

static u8 DHT11_Read_Byte(void)
{
    u8 i, dat = 0;
    for (i = 0; i < 8; i++)
    {
        dat <<= 1;
        dat |= DHT11_Read_Bit();
    }
    return dat;
}

static u8 DHT11_Read_Data(u8 *temp, u8 *humi)
{
    u8 buf[5] = {0};
    u8 i;
    DHT11_Rst();
    if (DHT11_Check() == 0)
    {
        for (i = 0; i < 5; i++)
        {
            buf[i] = DHT11_Read_Byte();
        }
        if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
        {
            *humi = buf[0];
            *temp = buf[2];
        }
    }
    else
        return 1;
    return 0;

    if (DHT11_Read_Data(&temperature, &humidity) == 0)
    {
        // 采集成功，发布数据
    }
    else
    {
        printf("DHT11 Read Data Failed!\r\n"); // 新增日志，确认采集状态
        // 发布失败提示
    }
}

// MQTT消息回调：处理“获取温湿度数据”指令
void mqtt_callback(MessageData *msg_data)
{
    LOS_ASSERT(msg_data);
    printf("Serial <- Received Topic: %.*s, Message: %.*s\r\n",
           msg_data->topicName->lenstring.len, msg_data->topicName->lenstring.data,
           msg_data->message->payloadlen, msg_data->message->payload);

    // 识别“获取温湿度数据”指令，触发采集并返回结果
    if (strncmp((char *)msg_data->message->payload, "gain temperature and humidity", msg_data->message->payloadlen) == 0)
    {
        char response[64] = {0};
        if (DHT11_Read_Data(&temperature, &humidity) == 0)
        {
            snprintf(response, sizeof(response), "传感器的温湿度: Temp:%d°C, Hum:%d%%", temperature, humidity);
        }
        else
        {
            strncpy(response, "传感器读取失败", sizeof(response) - 1);
        }

        // 发布温湿度结果到接收主题
        MQTTMessage reply;
        reply.qos = 0;
        reply.retained = 0;
        reply.payload = (void *)response;
        reply.payloadlen = strlen(response);
        char reply_topic[] = "expand:mqtt02-team12-dht11-02-1"; // 接收主题
        if (MQTTPublish(&mq_client, reply_topic, &reply) < 0)
        {
            printf("Serial <- MQTT Publish Failed!\r\n");
        }
        else
        {
            printf("Serial -> Sent Topic: %s, Message: %s\r\n", reply_topic, response);
        }
    }
}

// MQTT连接与初始化
int mqtt_connect(void)
{
    int rc = 0;
    NetworkInit(&n);
    NetworkConnect(&n, "broker.emqx.io", 1883); // 连接EMQ测试服务器

    // 分配MQTT缓冲区
    buf_size = 4096 + 1024;
    onenet_mqtt_buf = (unsigned char *)malloc(buf_size);
    onenet_mqtt_readbuf = (unsigned char *)malloc(buf_size);
    if (!onenet_mqtt_buf || !onenet_mqtt_readbuf)
    {
        printf("No memory for MQTT buffer!\r\n");
        return -2;
    }

    // 初始化MQTT客户端
    MQTTClientInit(&mq_client, &n, 1000, onenet_mqtt_buf, buf_size, onenet_mqtt_readbuf, buf_size);
    MQTTStartTask(&mq_client);

    // 配置MQTT连接参数
    data.keepAliveInterval = 30;
    data.cleansession = 1;
    data.clientID.cstring = "team12";
    data.username.cstring = "team12";
    data.password.cstring = "123456";
    mq_client.defaultMessageHandler = mqtt_callback;

    // 初始化DHT11
    hi_gpio_init();
    while (DHT11_Init())
    {
        printf("DHT11 Init Error, Retry...\r\n");
        usleep(100000);
    }
    printf("DHT11 Init Successful!!\r\n");

    // 连接MQTT服务器 & 订阅“指令主题”
    rc = MQTTConnect(&mq_client, &data);
    char cmd_topic[] = "expand:mqtt02-team12-dht11-02-2"; // 发送主题（用于接收指令）
    MQTTSubscribe(&mq_client, cmd_topic, 0, mqtt_callback);

    printf("MQTT Client Ready: Subscribe to %s, Wait for Command...\r\n", cmd_topic);
    return 0;
}

void mqtt_test(void) { mqtt_connect(); }